
#ifndef _MACRO_SOURCE_CODE_LUAVM_H
#define	_MACRO_SOURCE_CODE_LUAVM_H

#include <stdint.h>
#include <string.h>

#ifdef __cplusplus
#  include <lua.hpp>
#else
#  include <lua.h>
#  include <lualib.h>
#  include <lauxlib.h>
#endif

#ifdef _MSC_VER
#  define DLL_EXPORT __declspec( dllexport )
#  define DLL_IMPORT __declspec( dllimport )
#else
#  define DLL_EXPORT
#  define DLL_IMPORT
#endif

#ifdef __cplusplus
#  define EXTERN_C       extern "C"
#  define EXTERN_C_BEGIN extern "C" {
#  define EXTERN_C_END   }
#else
#  define EXTERN_C
#  define EXTERN_C_BEGIN
#  define EXTERN_C_END
#endif

#define VM_MSGID_NULL ( 0 )
#define VM_MSGID_USER ( 0x10000 )

/**
 * @brief luavm_post_message_t
 */

typedef int ( *luavm_post_message_t )( const char * name, intptr_t msgid, const void * buffer, size_t length );

/**
 * @brief get_vm_name
 */

static __inline size_t get_vm_name( lua_State * ctx, char * buffer, size_t length )
{
	size_t len = 0;

	const char * str = NULL;

	lua_getglobal( ctx, "vm" );

	lua_getfield( ctx, -1, "get_task_name" );

	lua_call( ctx, 0, 1 );

	str = lua_tolstring( ctx, -1, &len );

	if ( buffer && length > 0 )
	{
		memset( buffer, 0, length );

		if ( len > length )
		{
			len = length;
		}

		memcpy( buffer, str, len );
	}

	lua_pop( ctx, 2 );

	return len;
}

/**
 * @brief get_vm_post_func
 */

static __inline luavm_post_message_t get_vm_post_func( lua_State * ctx )
{
	luavm_post_message_t result = NULL;

	lua_getglobal( ctx, "vm" );

	lua_getfield( ctx, -1, "get_post_func" );

	lua_call( ctx, 0, 1 );

	result = ( luavm_post_message_t )lua_topointer( ctx, -1 );

	lua_pop( ctx, 2 );

	return result;
}

#ifdef USED_DLL_INIT_FUNC

EXTERN_C_BEGIN

luavm_post_message_t luavm_post_message = NULL;

DLL_EXPORT int dll_init( lua_State * ctx )
{
	luavm_post_message = get_vm_post_func( ctx );

	lua_pushboolean( ctx, 1 );

	return 1;
}

EXTERN_C_END

#endif

#endif	/* _MACRO_SOURCE_CODE_LUAVM_H */
